package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.service.impl.handler.FirstResourceFilterHandler;
import com.zzyl.service.impl.handler.SecondResourceFilterHandler;
import com.zzyl.service.impl.handler.ThirdResourceFilterHandler;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {
    @Autowired
    private ResourceMapper resourceMapper;
    /**
     * 根据条件查询资源列表
     *
     * @param resourceDto
     * @return
     */
    @Override
    public List<ResourceVo> list(ResourceDto resourceDto) {
        Resource resource = new Resource();
        BeanUtils.copyProperties(resourceDto, resource);
        if(!StringUtils.isEmpty(resource.getParentResourceNo())){
            resource.setParentResourceNo(NoProcessing.processString(resource.getParentResourceNo()));
        }

        List<Resource> list = resourceMapper.list(resource);

        return BeanUtil.copyToList(list, ResourceVo.class);
    }

    /**
     * 查询层级资源树
     *
     * @param resourceDto
     * @return
     */
    @Override
    public TreeVo tree(ResourceDto resourceDto) {
        //1. 查询所有的菜单资源
        Resource resource = Resource.builder()
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .dataState(SuperConstant.DATA_STATE_0)
                .build();
        List<Resource> allList = resourceMapper.list(resource);
        //2. 从所有的菜单资源中找到一级菜单
        TreeItemVo root = new TreeItemVo();
        root.setId("100000000000000");
        root.setLabel("智慧养老院");

        FirstResourceFilterHandler handler1 = new FirstResourceFilterHandler();
        SecondResourceFilterHandler handler2 = new SecondResourceFilterHandler();
        ThirdResourceFilterHandler handler3 = new ThirdResourceFilterHandler();

        handler1.setNextHandler(handler2);
        handler2.setNextHandler(handler3);

        handler1.filter(allList, root, resource.getParentResourceNo());

        //从所有的数据中找到一级目录
        /*List<Resource> firstList = allList.stream().filter(r -> {
            if (NoProcessing.processString(r.getParentResourceNo()).equals(resource.getParentResourceNo())) {
                return true;
            }else{
                return false;
            }
        }).collect(Collectors.toList());
        //把一级目录转换为前端需要的vo格式
        List<TreeItemVo> fistTreeItemVo = firstList.stream().map(r -> {
            TreeItemVo v = new TreeItemVo();
            v.setId(r.getResourceNo());
            v.setLabel(r.getResourceName());
            return v;
        }).collect(Collectors.toList());
        root.setChildren(fistTreeItemVo);


        //3. 查询每一个一级菜单中的二级菜单
        root.getChildren().stream().map(r -> {
            //3.1 遍历一级目录
            List<Resource> secondList = allList.stream().filter(item -> {
                //遍历所有的菜单数据
                if (item.getParentResourceNo().equals(r.getId())) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());

            List<TreeItemVo> secondTreeItemVo = secondList.stream().map(i -> {
                TreeItemVo v = new TreeItemVo();
                v.setId(i.getResourceNo());
                v.setLabel(i.getResourceName());
                return v;
            }).collect(Collectors.toList());

            r.setChildren(secondTreeItemVo);
            return r;
        }).collect(Collectors.toList());

        //4. 查询每一个二级菜单下面的三级菜单
        root.getChildren().stream().map(r -> {
            //r 表示的就是一级目录
            List<TreeItemVo> secondList = r.getChildren(); // 获取二级目录
            secondList.stream().map(item -> {
                //item 表示的是二级菜单
                List<Resource> thridList = allList.stream().filter(i -> {
                    //i 表示的是菜单
                    if (i.getParentResourceNo().equals(item.getId())) {
                        return true;
                    } else {
                        return false;
                    }
                }).collect(Collectors.toList());

                List<TreeItemVo> thirdTreeItemVo = thridList.stream().map(m -> {
                    TreeItemVo v = new TreeItemVo();
                    v.setId(m.getResourceNo());
                    v.setLabel(m.getResourceName());
                    return v;
                }).collect(Collectors.toList());

                item.setChildren(thirdTreeItemVo);
                return item;
            }).collect(Collectors.toList());
            return r;
        }).collect(Collectors.toList());*/

        //5. 封装并返回结果
        TreeVo treeVo = new TreeVo();
        treeVo.setItems(Arrays.asList(root));
        return treeVo;
    }

    /**
     * 保存菜单项
     *
     * @param resourceDto
     */
    @Override
    public void createResource(ResourceDto resourceDto) {
        //1. 创建pojo对象 并把dto的数据拷贝到pojo
        Resource resource = new Resource();
        BeanUtils.copyProperties(resourceDto, resource);

        //2. 查询父菜单的数据 然后设置子菜单的状态
        Resource parent = resourceMapper.selectResourceByParentNo(resourceDto.getParentResourceNo());
        resource.setDataState(parent.getDataState());

        //3. 设置当前新增菜单的编码
        resource.setResourceNo(createResourceNo(resourceDto));

        //4. 补充通用字段
        resource.setCreateTime(LocalDateTime.now());
        resource.setUpdateTime(LocalDateTime.now());
        resource.setCreateBy(1371500419615895553L);

        //4. 保存到数据库
        resourceMapper.insert(resource);
    }

    /**
     * 生成三级菜单
     *
     * @return
     */
    @Override
    public List<MenuVo> menus() {
        //0. 从ThreadLoacl中获取当前登录的用户
        String json = UserThreadLocal.getSubject();
        UserVo userVo = JSONUtil.toBean(json, UserVo.class);
        userVo.setId(1671403256519078138L);

        //1. 根据当前登录的用户查询所有的菜单
        List<MenuVo> menuList = resourceMapper.selectMenuByUserId(userVo.getId());

        //3. 判断是否有菜单如果没有 抛出异常
        if(ObjectUtil.isEmpty(menuList)){
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }

        //4. 根据父no分组统计每个父no下面的所有的子菜单
        Map<String, List<MenuVo>> mapData = menuList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));

        //5. 遍历所有的菜单 填充meat数据 然后通过自己的no找到自己的子菜单
        menuList.forEach(menu -> {
            menu.setRedirect("/"+menu.getName());
            menu.setMeta(MenuMetaVo.builder().title(menu.getName()).build());

            //6. 判断自己是否有子菜单 如果有就设置到自己的children属性
            List<MenuVo> subList = mapData.get(menu.getResourceNo());
            if(!ObjectUtil.isEmpty(subList)){
                menu.setChildren(subList);
            }
        });

        //7. 找到根据节点的子菜点 然后返回（一级菜单）
        return mapData.get(SuperConstant.ROOT_PARENT_ID);
    }

    private String createResourceNo(ResourceDto resourceDto) {
        //1. 如果创建的不是按钮 且层级高于3层 抛出异常
        if(!StringUtils.isEmpty(resourceDto.getResourceType()) && !"r".equals(resourceDto.getResourceType())){
            //判断层级
            if(NoProcessing.processString(resourceDto.getParentResourceNo()).length() > 12){
                throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
            }
        }

        //2. 查询父no下的所有的子菜单
        Resource resource = new Resource();
        resource.setParentResourceNo(NoProcessing.processString(resourceDto.getParentResourceNo()));
        List<Resource> list = resourceMapper.list(resource);

        //3. 判断子菜单是否存在 如果不存在 则直接在父no的基础上添加001
        if(null == list || list.size() == 0){
            return NoProcessing.createNo(resourceDto.getParentResourceNo(), false);
        }else{
            //4. 如果有子菜单 则找到最大的id 然后+1
            Long maxNo = list.stream().map(item -> Long.parseLong(item.getResourceNo())).max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(maxNo.toString(), true);
        }

    }
}
